/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package UserProfile;

import IMDBQuery.IMDBReader;
import IMDBQuery.MovieIMDB;
import bd.mdl.Rating;
import bd.ngc.ratingManager;
import com.hp.hpl.jena.ontology.OntModel;
import java.util.ArrayList;
import java.util.List;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Johnny
 */
public class EstereotipoProfile {

    public static void main(String arg[]) {
      //  generaEstereotipos();
        cargarPerfilesEstereotipo();
    //    System.out.println("");
    }

    public static ArrayList<ArrayList<Calificacion>> leeCalificacionesEstereotipos() {
        Configuration conf = Configuration.getInstance();
        ArrayList<Calificacion> grupo = new ArrayList<Calificacion>();
        ArrayList<ArrayList<Calificacion>> calificaciones = new ArrayList<ArrayList<Calificacion>>();
        ArrayList<Estereotipo> estereotipos = UserDataFileReader.leeEstereotipos(conf.getOUTFOLDER() + "stereotypes.dat");
        ratingManager fm = new ratingManager();
        List<Rating> ratings;
        for (Estereotipo estereotipo : estereotipos) {
            String[] ids = estereotipo.getIdsUsers().split(";");
            grupo = new ArrayList<Calificacion>();
            System.out.println("estereotipo" + estereotipo.getIdEstereotipo());
            List<PRatings> ratingsPromediados = new ArrayList<PRatings>();    
            for (String id : ids) {
                int idEst=Integer.parseInt(id);
                ratings = fm.listaRatings(idEst);
                //System.out.println(idEst+" "+ratings.size());
                for (Rating rating : ratings) {
                    boolean existe = false;
                    for(PRatings ratingP:ratingsPromediados)
                    {
                        if(rating.getRatingPK().getIdMovie()==ratingP.getIdMovie())
                        {
                            ratingP.setNumRatings(ratingP.getNumRatings()+1);
                            ratingP.setSumaRatings(ratingP.getSumaRatings()+rating.getRating());
                            ratingP.setRating((double)ratingP.getSumaRatings()/(double)ratingP.getNumRatings());
                           // System.out.println("promediando "+ ratingP.getSumaRatings()+ "  "+ratingP.getNumRatings()+"  "+ratingP.getRating());
                            existe=true;
                            break;
                        }                        
                    }
                    if(!existe)
                    {
                        PRatings rt = new PRatings();
                        rt.setIdEstereotipo(estereotipo.getIdEstereotipo());
                        rt.setIdMovie(rating.getRatingPK().getIdMovie());
                        rt.setNumRatings(1);
                        rt.setSumaRatings(rating.getRating());
                        rt.setRating(rating.getRating());
                        ratingsPromediados.add(rt);
                       // System.out.println("agregando "+ rt.getIdMovie());
                    }
                }
              //  System.out.println(ratingsPromediados.size());
                
            }
            for (PRatings rating : ratingsPromediados) {

                    Calificacion calificacion = new Calificacion(estereotipo.getIdEstereotipo(), rating.getRating(), rating.getIdMovie());
                    
                    grupo.add(calificacion);
                }
            calificaciones.add(grupo);
            //System.out.println("grupo--->"+grupo.size());
            //System.out.println(estereotipo.getIdEstereotipo());
        }

        return calificaciones;

    }

    public static void escribeUsuarios(List<User> usuarios, BufferedWriter bw, int id) {
        try {
            bw.newLine();
            String linea;
            linea = id + "::";
            for (User usuario : usuarios) {
                linea += usuario.getIdUser() + ";";
            }
            bw.write(linea);
        } catch (IOException ex) {
            Logger.getLogger(EstereotipoProfile.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static void generaEstereotipos() {
        Configuration conf = Configuration.getInstance();
        List<User> usuarios = UserDataFileReader.UserDataReadLines(conf.getDBUSERS());
        List<User> b18M = new ArrayList<User>(); //menores a 18 Masculino
        List<User> b18F = new ArrayList<User>(); //Menores a 18 Femenino
        List<User> d18a24M = new ArrayList<User>();
        List<User> d18a24F = new ArrayList<User>();
        List<User> d25a34M = new ArrayList<User>();
        List<User> d25a34F = new ArrayList<User>();
        List<User> d35a44M = new ArrayList<User>();
        List<User> d35a44F = new ArrayList<User>();
        List<User> d45a49M = new ArrayList<User>();
        List<User> d45a49F = new ArrayList<User>();
        List<User> d50a55M = new ArrayList<User>();
        List<User> d50a55F = new ArrayList<User>();
        List<User> s56M = new ArrayList<User>();
        List<User> s56F = new ArrayList<User>();
        for (User usuario : usuarios) {
            if (usuario.getEdad() < 18 && usuario.getSexo().equals("M")) {
                b18M.add(usuario);
            } else if (usuario.getEdad() < 18 && usuario.getSexo().equals("F")) {
                b18F.add(usuario);
            } else if (usuario.getEdad() >= 18 && usuario.getEdad() < 25 && usuario.getSexo().equals("M")) {
                d18a24M.add(usuario);
            } else if (usuario.getEdad() >= 18 && usuario.getEdad() < 25 && usuario.getSexo().equals("F")) {
                d18a24F.add(usuario);
            } else if (usuario.getEdad() >= 25 && usuario.getEdad() < 35 && usuario.getSexo().equals("M")) {
                d25a34M.add(usuario);
            } else if (usuario.getEdad() >= 25 && usuario.getEdad() < 35 && usuario.getSexo().equals("F")) {
                d25a34F.add(usuario);
            } else if (usuario.getEdad() >= 35 && usuario.getEdad() < 44 && usuario.getSexo().equals("M")) {
                d35a44M.add(usuario);
            } else if (usuario.getEdad() >= 35 && usuario.getEdad() < 45 && usuario.getSexo().equals("F")) {
                d35a44F.add(usuario);
            } else if (usuario.getEdad() >= 45 && usuario.getEdad() < 50 && usuario.getSexo().equals("M")) {
                d45a49M.add(usuario);
            } else if (usuario.getEdad() >= 45 && usuario.getEdad() < 50 && usuario.getSexo().equals("F")) {
                d45a49F.add(usuario);
            } else if (usuario.getEdad() >= 50 && usuario.getEdad() < 56 && usuario.getSexo().equals("M")) {
                d50a55M.add(usuario);
            } else if (usuario.getEdad() >= 50 && usuario.getEdad() < 56 && usuario.getSexo().equals("F")) {
                d50a55F.add(usuario);
            } else if (usuario.getEdad() >= 56 && usuario.getSexo().equals("M")) {
                s56M.add(usuario);
            } else if (usuario.getEdad() >= 56 && usuario.getSexo().equals("F")) {
                s56F.add(usuario);
            }
        }
        FileWriter fw;
        try {
            fw = new FileWriter(conf.getOUTFOLDER() + "stereotypes.dat");
            BufferedWriter bw = new BufferedWriter(fw);
            escribeUsuarios(b18M, bw, 1);
            escribeUsuarios(b18F, bw, 2);
            escribeUsuarios(d18a24M, bw, 3);
            escribeUsuarios(d18a24F, bw, 4);
            escribeUsuarios(d25a34M, bw, 5);
            escribeUsuarios(d25a34F, bw, 6);
            escribeUsuarios(d35a44M, bw, 7);
            escribeUsuarios(d35a44F, bw, 8);
            escribeUsuarios(d45a49M, bw, 9);
            escribeUsuarios(d45a49F, bw, 10);
            escribeUsuarios(d50a55M, bw, 11);
            escribeUsuarios(d50a55F, bw, 12);
            escribeUsuarios(s56M, bw, 13);
            escribeUsuarios(s56F, bw, 14);
            bw.close();
        } catch (IOException ex) {
            Logger.getLogger(EstereotipoProfile.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static void cargarPerfilesEstereotipo() {
        //obtengo las configuraciones del sistema
        Configuration conf = Configuration.getInstance();
        //obtengo la lista de peliculas definidas en DBMOVIES (base de peliculas)
        ArrayList<String> movies = UserDataFileReader.readLines(conf.getDBMOVIES());
        //obtengo las calificaciones agrupadas por usuario de la DBRATINGS (base de ratings)
        ArrayList<ArrayList<Calificacion>> agrupados = leeCalificacionesEstereotipos();
        Iterator<ArrayList<Calificacion>> ite = agrupados.iterator();
        //recorro los grupos, osea recorro los usuarios
        while (ite.hasNext()) {
            try {
                ArrayList<Calificacion> grupo = ite.next();
                if (!grupo.isEmpty()) {
                    System.out.println("");
                    System.out.println("Estereotipo " + grupo.get(0).getIdUser());

                    //obtengo el perfil-ontologia de usuario, si no existe se crea
                    OntModel estereotype = UserOntologyManager.getUserModel(grupo.get(0).getIdUser(), conf);
                    System.out.println("Tama;o---->"+grupo.size());
                    Iterator<Calificacion> ite2 = grupo.iterator();
                    //recorro las calificaciones del usuario
                    int i=0;
                    while (ite2.hasNext()) {
                        i++;
                        Calificacion cal = ite2.next();

                        System.out.print(i+"::");

                        //compruebo que la pelicula sea de train o de test
                        boolean isTest = isTestMovie(cal, conf);

                        //encuentro la pelicula en la lista
                        String movieLine = findMovieLine(cal.getIdMovie(), movies);

                        //cargo la MovieIMDB
                        MovieIMDB movieIMDb = IMDBReader.getMovieIMDB(movieLine, conf);

                        //cargo la pelicula en el modelo
                        if (movieIMDb != null) {
                            estereotype = UserOntologyManager.fillOntology(estereotype, movieIMDb, cal, conf, isTest);
                        }
                    }

                    //propago los DOI en las caracteristicas semanticas de los contenidos formalizados en la ontologia
                    estereotype = UserOntologyManager.doiPropagation(estereotype, grupo.get(0).getIdUser(), conf,false);

                    //guardo el perfil-ontolog�a
                    try {
                        String path = conf.getONTOLOGYSTEREOTYPE() + grupo.get(0).getIdUser() + ".owl";
                        FileWriter f1 = new FileWriter(path);
                        BufferedWriter b1 = new BufferedWriter(f1);
                        estereotype.write(b1, "RDF/XML");
                        b1.close();
                        estereotype.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        System.out.println(e.getMessage());

                    }
                }
            } catch (NoExisteLaOntologiaException e) {
                // TODO Auto-generated catch block
                System.out.println("UserProfile.cargarPerfilesUsuario() Error: " + e.getMessage());
            } catch (NoSePudoPersistirElModeloException e) {
                // TODO Auto-generated catch block
                System.out.println("UserProfile.cargarPerfilesUsuario() Error: " + e.getMessage());
            }
        }
    }

    /**
     * Metodo encargado de crear las ontologias de peliculas de las bases
     * MovieLens
     */
    public static void cargarPelicula() {
        try {
            //obtengo las configuraciones del sistema
            Configuration conf = Configuration.getInstance();

            //obtengo la lista de peliculas definidas en DBMOVIES (base de peliculas)
            ArrayList<String> movies = UserDataFileReader.readLines(conf.getDBMOVIES());

            //obtengo el perfil-ontologia de pelicula, si no existe se crea
            OntModel movie = UserOntologyManager.getMovieModel(conf);
            int count = 0;
            while (movies.size() >= count) {
                count++;
                //encuentro la pelicula en la lista
                String movieLine = findMovieLine(count, movies);
                //cargo la MovieIMDB
                MovieIMDB movieIMDb = IMDBReader.getMovieIMDB(movieLine, conf);
                System.out.println("|" + count + "sss" + movieIMDb);

                //cargo la pelicula en el modelo
                if (movieIMDb != null) {
                    movie = UserOntologyManager.fillOntology(movie, movieIMDb, conf);
                }
                //guardo el perfil-ontolog�a
                String path = conf.getMOVIESIMDB();
                System.err.println(path);
                FileWriter f1;
                try {
                    f1 = new FileWriter(path);
                    BufferedWriter b1 = new BufferedWriter(f1);
                    movie.write(b1, "RDF/XML");
                    b1.close();

                } catch (IOException ex) {
                    Logger.getLogger(UserProfile.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
            movie.close(); //cerramos la ontologia
        } catch (NoSePudoPersistirElModeloException ex) {
            Logger.getLogger(UserProfile.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoExisteLaOntologiaException ex) {
            Logger.getLogger(UserProfile.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    /**
     * Retorna true en caso de que la pelicula calificada sea de test
     *
     * @param calification es la calificacion que un usuario da a una pelicula
     * @param conf es la configuracion del sistema
     * @return true si la pelicula es de test, false en caso contrario
     */
    private static boolean isTestMovie(Calificacion calificacion, Configuration conf) {

        //obtengo las peliculas test agrupadas por usuario de DBTEST (base de peliculas para test)
        ArrayList<ArrayList<Calificacion>> agrupados = UserDataFileReader.RatingsReadLines(conf.getDBTEST());
        Iterator<ArrayList<Calificacion>> ite = agrupados.iterator();
        //recorro los grupos, osea recorro los usuarios
        while (ite.hasNext()) {
            ArrayList<Calificacion> grupo = ite.next();
            if (!grupo.isEmpty()) {
                //obtengo el id del usuario puntero
                int iduser = grupo.get(0).getIdUser();
                /*si el usuario puntero coinside con el usuario buscado 
                 se comprueba si la pelicula calificada es de test*/
                if (iduser == calificacion.getIdUser()) {
                    Iterator<Calificacion> ite2 = grupo.iterator();
                    //recorro las calificaciones del usuario puntero
                    while (ite2.hasNext()) {
                        Calificacion cal = ite2.next();
                        //compruebo que la pelicula buscada este entre las peliculas test del usuario
                        if (cal.getIdMovie() == calificacion.getIdMovie()) {
                            return true;
                        }
                    }
                    //si no esta entre las peliculas test retorno false;
                    return false;
                }
            }
        }
        return false;
    }

    /**
     * Retorna la informacion del contenido identificado con
     * <code>idMovie</code> de la lista de contenidos <code>movies</code>
     *
     * @param idMovie identificador del contenido buscado
     * @param movies lista de los contenidos definidos en la base de datos de
     * MovieLens
     * @return informacion del contenido buscado
     */
    private static String findMovieLine(int idMovie, ArrayList<String> movies) {
        Iterator<String> iterator = movies.iterator();
        while (iterator.hasNext()) {
            String pivot = iterator.next();
            String campos[] = pivot.split("::");
            int idMoviePivot = Integer.parseInt(campos[0]);

            if (idMovie == idMoviePivot) {
                return pivot;
            }
        }
        return null;
    }
}
